// -*- c++ -*-

#version 330 core

in VS_OUT
  {
    vec3 frag_pos;
    vec3 frag_norm;
    vec3 frag_color;
    vec2 frag_tex_coords;
  }
vs_in;

out vec4 out_color_v4;

uniform sampler2D sampler;

layout (std140) uniform Material
{
  vec3 ambient;
  vec3 diffuse;
  vec3 specular;
  float shininess;
}
material;

struct Light
{
  vec3 pos;
  vec3 ambient;
  vec3 diffuse;
  vec3 specular;
  int  type;
};

layout (std140) uniform Lighting
{
  vec3 view_pos;
  Light lights[4];
}
lighting;

vec3 calc_light_directional ( int light )
{
  vec3 ambient_col = lighting.lights[light].ambient * material.ambient;
  
  // diffuse
  // vec3 norm = m3_norm_mat * vs_in.frag_norm;
  vec3 light_dir = normalize(lighting.lights[light].pos);
  float diff_val = max(dot(vs_in.frag_norm, light_dir), 0.f);
  vec3 diff_col = lighting.lights[light].diffuse * (diff_val * material.diffuse);

  // specular ?
  vec3 view_dir = normalize(lighting.view_pos - vs_in.frag_pos);
  vec3 reflect_dir = reflect(-light_dir, vs_in.frag_norm);
  float spec = pow(max(dot(view_dir, reflect_dir), 0.f), material.shininess);
  vec3 spec_col = lighting.lights[light].specular * (spec * material.specular);
  
  return (ambient_col + diff_col + spec_col);
}

vec3 calc_light_omni ( int light )
{
  vec3 ambient_col = lighting.lights[light].ambient * material.ambient;
  
  // diffuse
  // vec3 norm = m3_norm_mat * vs_in.frag_norm;
  vec3 light_dir = normalize(lighting.lights[light].pos - vs_in.frag_pos);
  float diff_val = max(dot(vs_in.frag_norm, light_dir), 0.f);
  vec3 diff_col = lighting.lights[light].diffuse * (diff_val * material.diffuse);

  // specular
  vec3 view_dir = normalize(lighting.view_pos - vs_in.frag_pos);
  vec3 reflect_dir = reflect(-light_dir, vs_in.frag_norm);
  float spec = pow(max(dot(view_dir, reflect_dir), 0.f), material.shininess);
  vec3 spec_col = lighting.lights[light].specular * (spec * material.specular);
  
  return (ambient_col + diff_col + spec_col);
}

void main ()
{
  vec3 col = vec3(0.f, 0.f, 0.f);
  for (int l = 0; l < 4; l++)
    {
      switch (lighting.lights[l].type)
        {
        case 0: // None
          break;
        case 1: // Directional
          col += calc_light_directional(l);
          break;
        case 2: // Omni
          col += calc_light_omni(l);
          break;
        default:
            break;
        }
    }
  out_color_v4 = vec4(col * vs_in.frag_color, 1.f) * texture(sampler, vs_in.frag_tex_coords);
}
